package com.sangeng.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.sangeng.constants.SystemConstants;
import com.sangeng.entity.LoginUser;
import com.sangeng.entity.Menu;
import com.sangeng.mapper.MenuMapper;
import com.sangeng.service.IMenuService;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.sangeng.utils.BeanCopyUtils;
import com.sangeng.utils.SecurityUtils;
import com.sangeng.vo.MenuVo;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.stereotype.Service;

import java.util.*;
import java.util.stream.Collectors;

/**
 * <p>
 * 菜单权限表 服务实现类
 * </p>
 *
 * @author lz
 * @since 2024-07-24
 */
@Service
public class MenuServiceImpl extends ServiceImpl<MenuMapper, Menu> implements IMenuService {

    @Override
    public List<String> selectPermsByUserId(Long id) {
        //如果是管理员，返回所有的权限
        if (id == 1L) {
            LambdaQueryWrapper<Menu> wrapper = new LambdaQueryWrapper<>();
            wrapper.in(Menu::getMenuType, SystemConstants.MENU, SystemConstants.BUTTON);
            wrapper.eq(Menu::getStatus, SystemConstants.STATUS_NORMAL);
            List<Menu> menus = list(wrapper);
            return menus.stream()
                    .map(Menu::getPerms)
                    .collect(Collectors.toList());
        }
        //否则返回所具有的权限
        return getBaseMapper().selectPermsByUserId(id);
    }

    @Override
    public List<Menu> selectRouterMenuTreeByUserId(Long userId) {
        MenuMapper menuMapper = getBaseMapper();
        List<Menu> menus = null;
        //判断是否是管理员
        if (SecurityUtils.isAdmin()) {
            //如果是 获取所有符合要求的Menu
            menus = menuMapper.selectAllRouterMenu();
        } else {
            //否则  获取当前用户所具有的Menu
            menus = menuMapper.selectRouterMenuTreeByUserId(userId);
        }

        //构建tree
        //先找出第一层的菜单  然后去找他们的子菜单设置到children属性中
        List<Menu> menuTree = builderMenuTree(menus, 0L);
        return menuTree;
    }

    @Override
    public List<MenuVo> selectMenuTree() {
        //获取token 解析获取userid
        Authentication authentication = SecurityContextHolder.getContext().getAuthentication();
        LoginUser loginUser = (LoginUser) authentication.getPrincipal();
        //获取userid
        Long userId = loginUser.getUser().getId();
        List<Menu> menus = selectRouterMenuTreeByUserId(userId);
        return handlerMenuTree(menus);
    }

    @Override
    public Map selectMenuTreeByRoleId(Long roleId) {
        // 根据角色id 获取所有菜单
        List<Menu> menus = getBaseMapper().selectMenuTreeByRoleId(roleId);
        List<Long> ids = menus.stream().map(Menu::getId).collect(Collectors.toList());
        Map map = new HashMap<>();
        map.put("checkedKeys", ids);
        map.put("menus", selectMenuTree());
        return map;
    }

    private List<MenuVo> handlerMenuTree(List<Menu> menus) {
        List<MenuVo> menuTree = new ArrayList<>();
        menus.forEach(menu -> {
            MenuVo menuVo = new MenuVo();
            menuVo.setId(String.valueOf(menu.getId()));
            menuVo.setParentId(String.valueOf(menu.getParentId()));
            menuVo.setLabel(menu.getMenuName());
            if (menu.getChildren() != null && !menu.getChildren().isEmpty()) {
                menuVo.setChildren(handlerMenuTree(menu.getChildren()));
            } else {
                menuVo.setChildren(Collections.emptyList());
            }
            menuTree.add(menuVo);
        });
        return menuTree;
    }


    private List<Menu> builderMenuTree(List<Menu> menus, Long parentId) {
        List<Menu> menuTree = menus.stream()
                .filter(menu -> menu.getParentId().equals(parentId))
                .map(menu -> menu.setChildren(getChildren(menu, menus)))
                .collect(Collectors.toList());
        return menuTree;
    }

    /**
     * 获取存入参数的 子Menu集合
     *
     * @param menu
     * @param menus
     * @return
     */
    private List<Menu> getChildren(Menu menu, List<Menu> menus) {
        List<Menu> childrenList = menus.stream()
                .filter(m -> m.getParentId().equals(menu.getId()))
                .map(m -> m.setChildren(getChildren(m, menus)))
                .collect(Collectors.toList());
        return childrenList;
    }
}
